namespace BoxPlayer
{
    class T_Box_Core;    //
    class T_Box_Control; //
    class T_Box_Media;   //
    class T_Box_Context; //
};

#ifndef T_BOX_MEDIA_H
#define T_BOX_MEDIA_H

#include "stable.h"
#include "t_box.h"
#include "t_av_packet.h"
#include "t_box_seek_manager.h"
#include "input/input.h"

namespace BoxPlayer
{
    class T_Box_Core : public QObject
    {
        Q_OBJECT
    protected:
        T_DECLARE_PRIVATE(T_Box_Core);
    public:
        explicit T_Box_Core(T_Box_Sequence *a_sequence);
        virtual ~T_Box_Core();
        bool isValid();
        T_Box_Control *globalControl();
        T_Box_Sequence *sequence();
        T_Clock *timeline();
        T_Box_Seek_Manager *seekManager();
    };

    class T_Box_Control : public QObject, public T_Box_Seekable
    {
        Q_OBJECT
    protected:
        T_DECLARE_PRIVATE(T_Box_Control);
    public:
        explicit T_Box_Control(T_Box_Core *a_core);
        virtual ~T_Box_Control();
        bool isValid();
        T_Box_Core *core();
        AVFormatContext	*formatContext();
        QSharedPointer<T_AV_Packet> headPacket(bool a_all_media = false);
        QSharedPointer<T_AV_Packet> readPacket(bool a_all_media = false);
        QSharedPointer<T_AV_Packet> enqueuePacket();
        virtual qint64 seekMe(T_Box_Seek_Manager *a_seek_mgr, qint64 a_msec);
        qint64 contentDuration();
        T_Box_Media *openMedia(AVMediaType a_media_type);
        QList<T_Box_Media *> &mediaList();
    protected:
        bool p_hasOpenMedia();
        QSharedPointer<T_AV_Packet> p_readPacket(bool a_all_media);
    };

    class T_Box_Media : public QObject
    {
        Q_OBJECT
    protected:
        T_DECLARE_PRIVATE(T_Box_Media);
    public:
        explicit T_Box_Media(T_Box_Control *a_control, int a_index);
        virtual ~T_Box_Media();
        enum AVMediaType mediaType();
        bool open();
        bool isOpen();
        T_Box_Core *core();
        T_Box_Control *control();
        int streamIndex();
        AVStream *stream();
        AVCodecContext *codecContex();
        AVCodec *codec();
        T_AVFrame *frame();
        T_AV_Packet_Queue *packetQueue();
        void flushBuffers();
        bool isAudio();
        bool isVideo();
        T_AVRational time_base();
        T_AVRational avg_frame_rate();
        T_AVRational r_frame_rate();
        qint64 &maxTiming();
    protected:
        friend class T_Box_Control;
        qint64 &packetCount();
    };

    class T_Box_Context
        : public T_Box_Thread
        , public T_Atomic
        , public T_Box_Seekable
    {
        Q_OBJECT
    protected:
        T_DECLARE_PRIVATE(T_Box_Context);
    public:
        explicit T_Box_Context(T_Box_Core *a_core);
        virtual ~T_Box_Context();
        T_Box_Core *core();
        T_Box_Control *control();
        T_Box_Media *audio();
        T_Box_Media *video();
        bool openAudio();
        bool openVideo();
        QSharedPointer<T_AV_Packet> headPacket(bool a_all_media = false);
        QSharedPointer<T_AV_Packet> readPacket(bool a_all_media = false);
        QSharedPointer<T_AV_Packet> enqueuePacket();
        virtual qint64 seekMe(T_Box_Seek_Manager *a_seek_mgr, qint64 a_msec);
    protected:
        virtual void run();
    };

};
#endif // T_BOX_MEDIA_H
